import type { FormItemProps, InputProps, ISelectProps } from 'element-plus'
import type { JSX } from 'vue/jsx-runtime'

export enum ComponentNameEnum {
  INPUT = 'Input',
  Select = 'Select'
}

type CamelCaseComponentName = keyof typeof ComponentNameEnum extends infer K
  ? K extends string
    ? K extends `${infer A}_${infer B}`
      ? `${Capitalize<Lowercase<A>>}${Capitalize<Lowercase<B>>}`
      : Capitalize<Lowercase<K>>
    : never
  : never

export type ComponentName = CamelCaseComponentName

interface InputComponentProps extends Partial<InputProps> {
  on?: {
    change?: (value: string | number) => void
  }
  slots?: {
    prefix?: (...args: any[]) => JSX.Element | null
    suffix?: (...args: any[]) => JSX.Element | null
    prepend?: (...args: any[]) => JSX.Element | null
    append?: (...args: any[]) => JSX.Element | null
  }
}

export interface SelectOption {
  label?: string
  disabled?: boolean
  value?: any
  key?: string | number
  [key: string]: any
}

export interface SelectComponentProps extends Partial<ISelectProps> {
  // 数据源的字段别名
  props?: {
    key?: string
    label?: string
    value?: string
  },
  on?: {
    change?: (value: any) => void
    clear?: () => void
    blur?: (event: FocusEvent) => void
    focus?: (event: FocusEvent) => void
  }
  slots?: {
    empty?: (...args: any[]) => JSX.Element | null
    loading?: (...args: any[]) => JSX.Element | null
  }
  options?: SelectOption[]
}

export interface FormSetProps {
  field: string
  path: string
  value: any
}

export interface ColProps {
  span?: number
  xs?: number
  sm?: number
  md?: number
  lg?: number
  xl?: number
}

export interface FormSchema {
  /**
  * 唯一标识
  */
  field: string
  label?: string
  colProps?: ColProps
  componentProps?: InputComponentProps | SelectComponentProps | any
  formItemProps?: Partial<FormItemProps>

  /**
   * 渲染的组件名称
   */
  component: ComponentName

  /**
   * 初始值
   */
  value?: any

   /**
   * 是否隐藏，如果为true，会连同值一同删除，类似v-if
   */
   remove?: boolean

  /**
   * @returns 远程加载下拉项
   */
  optionApi?: (params?: any) => Promise<any>
}

